/**
 ** @author:	   浓咖啡
 ** @date:	   2018.8.29
 ** @brief:      对抓到数据包进行解析
 */

#include <linux/if_ether.h>
#include <linux/ip.h>
#include <arpa/inet.h>
#include "convert.h"
#include "string.h"

static void parse_ethernet(const u_char *packet);
static void parse_ip(const u_char *ipdata);

/**
 * @brief 解析数据包
 * @param packet 数据包原始数据
 * @param len 数据包长度
 */
void code(const u_char *packet, int len)
{
    parse_ethernet(packet);
}

static void parse_ethernet(const u_char *packet)
{
    printf("--------------------------------------------\n");
    printf("Ethernet II Layer\n\n");

    int i;

    //以太网头部
    struct ethhdr *mh = (struct ethhdr *)(packet);

    //源MAC地址
    printf("Src: ");
    for(i=0; i<ETH_ALEN; i++){
        printf("%x ", mh->h_dest[i]);
    }

    printf("\n");

    //目的MAC地址
    printf("Dst: ");
    for(i=0; i<ETH_ALEN; i++){
        printf("%x ", mh->h_source[i]);
    }
    printf("\n");

    //帧类型
    char type[64] = "Unknow";
    mh->h_proto = ntohs(mh->h_proto);
    switch (mh->h_proto) {
    case 0x0800:
        strcpy(type, "IP");
        printf("Type: %s(0x%04x)\n", type, mh->h_proto);
        parse_ip(packet + ETH_HLEN);
        break;
    default:
        break;
    }
}

static void parse_ip(const u_char *ipdata)
{
    printf("--------------------------------------------\n");
    printf("IP Layer\n\n");

    struct iphdr *iph = (struct iphdr *)ipdata;
    printf("Version: %d\n", iph->version);
    printf("Header Length: %d Bytes\n", iph->ihl * 4);
    printf("Total Length: %d Bytes\n", ntohs(iph->tot_len));
    printf("Identification: 0x%x\n", ntohs(iph->id));
    __be16 frag_off = ntohs(iph->frag_off);
    if(frag_off & (1<<14)){  //是否分片的标志
        printf("Don't Fragment\n");
    }else{
        printf("Fragment\n");  //分片先不做处理
    }

    printf("Fragment offset: 0x%x\n", frag_off & 0x1FFF);
    printf("Time to live: %d\n", iph->ttl);
    printf("Header checksum: 0x%x\n", ntohs(iph->check));

    struct in_addr addr;
    addr.s_addr = iph->saddr;
    printf("Source Ip: %s\n", inet_ntoa(addr));
    addr.s_addr = iph->daddr;
    printf("Dest Ip: %s\n", inet_ntoa(addr));

    char type[64] = "Unknow";
    switch (iph->protocol) {
    case 0x06:  //TCP协议
        strcpy(type, "TCP");
        printf("Type: %s(0x%x)\n", type, iph->protocol);
        //parse_tcp(iph + iph->ihl * 4);
        break;
    default:
        break;
    }
}
